package net.maku.framework.mybatis.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import net.maku.framework.common.query.Query;
import net.maku.framework.mybatis.utils.MBPUtils;

import java.beans.Introspector;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
import java.util.List;
import java.util.regex.Pattern;

/**
 * @author hy
 * @version 1.0
 */
public interface HService<T> extends IService<T> {

    Pattern GET_PATTERN = Pattern.compile("^get[A-Z].*");
    Pattern IS_PATTERN = Pattern.compile("^is[A-Z].*");
    String TEMPLATE = "JSON_CONTAINS( {}, '{}' )";
    String OR = "or ";

    default LambdaQueryChainWrapper<T> getLQCWrapper() {
        return MBPUtils.buildLQCWrapper(this.getEntityClass(), this.getBaseMapper());
    }

    default LambdaQueryWrapper<T> getLQWrapper() {
        return MBPUtils.buildLQWrapper(this.getEntityClass());
    }

    default QueryWrapper<T> getQWrapper() {
        return MBPUtils.buildQWrapper(this.getEntityClass());
    }

    default IPage<T> buildPage(Query query) {
        return MBPUtils.buildPage(query, this.getEntityClass());
    }

    default String jsonContains(SFunction<T, ?> filed, List<? extends Number> list) {
        StrBuilder builder = StrBuilder.create();
        try {
            Method method = filed.getClass().getDeclaredMethod("writeReplace");
            method.setAccessible(Boolean.TRUE);
            SerializedLambda serializedLambda = (SerializedLambda) method.invoke(filed);
            String getter = serializedLambda.getImplMethodName();

            if (GET_PATTERN.matcher(getter).matches()) {
                getter = getter.substring(3);
            } else if (IS_PATTERN.matcher(getter).matches()) {
                getter = getter.substring(2);
            }

            for (char c : Introspector.decapitalize(getter).toCharArray()) {
                if (Character.isUpperCase(c)) {
                    builder.append("_").append(Character.toLowerCase(c));
                } else {
                    builder.append(c);
                }
            }
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }

        StrBuilder result = StrBuilder.create();
        if (CollUtil.isNotEmpty(list)) {
            for (Number number : list) {
                if (result.isEmpty()) {
                    result.append(StrUtil.format(TEMPLATE, builder.toString(), List.of(number)));
                } else {
                    result.append(OR).append(StrUtil.format(TEMPLATE, builder.toString(), List.of(number)));
                }
            }
        }
        return result.toString();
    }

}